using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Odb_base.Interop;
using Odb_base.Interop.Interfaces;
using COMTypes = System.Runtime.InteropServices.ComTypes;
using STATSTG=System.Runtime.InteropServices.ComTypes.STATSTG;

namespace Odb_base
{
  /// <summary>
  /// Create an optical disk image (aka ISO File)
  /// </summary>
  public class ImageCreator
  {
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int SHCreateStreamOnFile(string pszFile, uint grfMode, out IStream ppstm);

    public void CreateISOImage(string outputName, string treeRoot, string volumeName)
    {
      MsftFileSystemImage fs = new MsftFileSystemImage();
      IFsiDirectoryItem dir = fs.Root;
      MsftDiscFormat2Data data = new MsftDiscFormat2Data();
      data.ClientName = volumeName;
      fs.FileSystemsToCreate = FsiFileSystems.FsiFileSystemISO9660 |
                               FsiFileSystems.FsiFileSystemJoliet;
      fs.VolumeName = volumeName;
      dir.AddTree(treeRoot, false);
    ////  FileSystemImageResult res = fs.CreateResultImage();
    //////TODO:
    ////  FsiStream stream = res.ImageStream;
    ////  return CreateISOFile(outputName, (System.Runtime.InteropServices.ComTypes.IStream)stream);
    }

    public static  bool CreateISOFile(string file, IStream stream)
    {
      //Create the directory if it does not exist
      if (string.IsNullOrEmpty(Path.GetFileName(file)))
      {
        return false;
      }
      string path = Path.GetDirectoryName(file);
      if (!Directory.Exists(path))
      {
        Directory.CreateDirectory(path);
      }
      IStream newStream;
      SHCreateStreamOnFile(file, 0x1001, out newStream);
      STATSTG stat;
      stream.Stat(out stat, 0x0);
      IntPtr inBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int)));
      IntPtr outBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int)));
      try
      {
        stream.CopyTo(newStream, stat.cbSize, inBytes, outBytes);
      }
      catch (Exception r)
      {
        Console.WriteLine(r.ToString());
      }
      finally
      {
        Marshal.FreeHGlobal(inBytes);
        Marshal.FreeHGlobal(outBytes);
      }
      return true;
    }
  }
}